﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.IO;
using System.Threading;
using Portal.FileSystemData;

namespace Portal.Modules.ImageBrowser
{
  /// <summary>
  /// A class to update dependend files of the directory tree.
  /// </summary>
  internal class CacheUpdater
  {
    static Dictionary<string, CacheUpdater> _runningCacheUpdater = new Dictionary<string, CacheUpdater>();
    volatile bool _exitUpdateProcess = false;
    Thread _runningThread;
    string _key;
    UpdateMethod _updateMethod;

    public delegate void UpdateMethod(FileSystemData.FileSystemWrapper fileSys);

    public CacheUpdater(string key, UpdateMethod method)
    {
      _key = key;
      _updateMethod = method;
    }

    public void UpdateCache(string path, DirectoryWrapper directory)
    {
      // Make sure no update for this key is running.
      lock (_runningCacheUpdater)
      {
        CacheUpdater updater;
        if (_runningCacheUpdater.TryGetValue(_key, out updater))
        {
          updater.StopThumbnailUpdate();
        }

        try
        {
          // Delete the cached files, to build them new.
          if (Directory.Exists(path))
            Directory.Delete(path, true);
        }
        catch {}

        // Start the update Thread.
        _runningThread = new Thread(new ParameterizedThreadStart(UpdateDirectoryEntry));
        _runningThread.Priority = ThreadPriority.BelowNormal;
        _runningThread.IsBackground = false;

        _runningCacheUpdater.Add(_key, this);
        _runningThread.Start(directory);
      }
    }

    private void StopThumbnailUpdate()
    {
      // Check if a thread is running.
      if (_runningThread != null)
      {
        // Signalize the abort and wait for the thread exiting.
        _exitUpdateProcess = true;
        _runningThread.Join();
        _exitUpdateProcess = false;
      } 
    }

    private void UpdateDirectoryEntry(object directory)
    {
      try
      {
        UpdateDirectory(directory as DirectoryWrapper);
      }
      catch (Exception ex)
      {
      }
      finally
      {
        _runningThread = null;
        _runningCacheUpdater.Remove(_key);
      }
    }

    private void UpdateDirectory(DirectoryWrapper directoryWrapper)
    {
      if (directoryWrapper == null)
        throw new ArgumentNullException("directoryWrapper");

      foreach (var file in directoryWrapper.Files)
      {
        // Cancel requested?
        if (_exitUpdateProcess)
          return;

        _updateMethod(file);
      }

      foreach (var dir in directoryWrapper.SubDirectories)
      {
        // Cancel requested?
        if (_exitUpdateProcess)
          return;

        _updateMethod(dir);
        UpdateDirectory(dir);
      }
    }

  }
}